
local function fixCode(code)
	code = code:gsub("cpu%.", "cpu%->")
	if
		not code:find("lni") and
		not code:find("instrloadpre") and
		not code:find("jmp") and
		not code:find("ldi")
	then code = code.." cpu->cycle++;" end
	return code
end
local function lineFromInstr(instr)
	local cycleLines = {}
	for cycle = 0, 7 do
		if instr and instr.ccode[cycle+1] then
			cycleLines[cycle+1] = string.format("cpu_instr_%i_%i", instr.opcode, cycle)
		else
			cycleLines[cycle+1] = 0
		end
	end
	return string.format("{%s},", table.concat(cycleLines, ","))
end
local function codeFromInstr(instr, lines)
	for i, code in ipairs(instr.ccode) do
		local cycle = i-1
		local line = string.format(
			"void cpu_instr_%i_%i(struct CPU* const cpu, struct Memory* const mem) { %s }",
			instr.opcode, cycle,
			fixCode(code)
		)
		table.insert(lines, line)
	end
end

local ccode = [[
// Auto-generated by gendefs.lua

%s

CPUInstruction CPUInstructions[256][8] = {
	%s
};
]]
local function ccodeFromArch(arch)
	local instrsByOpcode = {}
	for i, instr in ipairs(arch.instructions) do
		if instr.opcode then instrsByOpcode[instr.opcode] = instr end
	end
	
	local instrLines = {}
	local funcLines = {}
	for opcode = 0, 255 do
		local instr = instrsByOpcode[opcode]
		instrLines[opcode+1] = lineFromInstr(instr)
		if instr then codeFromInstr(instr, funcLines) end
	end
	return string.format(ccode,
		table.concat(funcLines, "\n"),
		table.concat(instrLines, "\n\t")
	)
end

local arch = dofile("../rom-8608-defs.lua")
local fo = io.open("instructions_gen.c", "w")
fo:write(ccodeFromArch(arch))
fo:close()
